package com.xzzz.backend.bsms.server.rbac.sys.dict.name;

import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.PropertyName;
import com.fasterxml.jackson.databind.SerializationConfig;
import com.fasterxml.jackson.databind.ser.BeanPropertyWriter;
import com.fasterxml.jackson.databind.ser.BeanSerializerModifier;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;

@Slf4j
public class DictNameSerializerModifier extends BeanSerializerModifier {

    private final DictCache dictCache;

    public DictNameSerializerModifier(DictCache dictCache) {
        this.dictCache = dictCache;
    }

    /**
     * 在对象第一次序列化时, 修改对象的序列化方式
     *
     * @param config         序列化配置
     * @param beanDesc       对象说明
     * @param beanProperties 对象字段配置
     * @return 对象字段配置集合
     */
    @Override
    public List<BeanPropertyWriter> changeProperties(SerializationConfig config, BeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) {

        List<BeanPropertyWriter> newFields = new ArrayList<>();

        for (BeanPropertyWriter writer : beanProperties) {

            DictName dict = writer.getAnnotation(DictName.class);
            if (dict != null) {
                String groupId = StrUtil.isBlank(dict.value()) ? dict.groupId() : dict.value();
                if (StrUtil.isBlank(groupId)) {
                    log.warn("字段[{}.{}]的字典GroupId为空, 不会为其生成字典名.", beanDesc.getClassInfo().getName(), writer.getName());
                    continue;
                }
                // 字典值需要有字典名时, 创建字典名的 BeanPropertyWriter, 格式为字典值 + @dictName.suffix()
                String newFiledName = writer.getName() + dict.suffix();
                // 创建字典名字段
                BeanPropertyWriter newFiled = new DictNameBeanPropertyWriter(writer, PropertyName.construct(newFiledName));
                // 设置字段序列化方式
                newFiled.assignSerializer(new DictNameSerializer(dictCache, dict.groupId()));
                newFiled.assignNullSerializer(new DictNameSerializer(dictCache, dict.groupId()));
                newFields.add(newFiled);
            }

        }
        beanProperties.addAll(newFields);
        return beanProperties;
    }

    /**
     * 通过继承改变 {@link BeanPropertyWriter#BeanPropertyWriter(BeanPropertyWriter base, PropertyName name)}
     * 的访问权限。
     */
    public static class DictNameBeanPropertyWriter extends BeanPropertyWriter {
        public DictNameBeanPropertyWriter(BeanPropertyWriter base, PropertyName name) {
            super(base, name);
        }
    }
}
